package com.world.cat.app;

import com.world.cat.app.utils.JwtUtil;
import com.world.cat.model.sys.User;
import com.world.cat.service.sys.ApiVerifyService;
import com.world.cat.service.sys.TokenInfoService;
import com.world.cat.service.sys.UserService;
import com.world.common.pojo.Result;
import com.world.common.util.JsonUtil;
import com.world.common.util.SessionUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Created by gang on 2017/11/2.
 */
public class AppTokenInterceptor implements HandlerInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(AppTokenInterceptor.class);
    @Resource
    private ApiVerifyService apiVerifyService;
    @Resource
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        return validateToken(httpServletRequest, httpServletResponse);
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    private boolean validateToken(HttpServletRequest request, HttpServletResponse response) {
        String tokenStr = request.getParameter("token");
        String token = request.getHeader("token");
        if (token == null && tokenStr == null) {
            logger.info("======================token is null");
            dealErrorReturn(request, response, JsonUtil.objectToJson(new Result(false, "缺少token，无法验证")));
            return false;
        }
        if (tokenStr != null) {
            token = tokenStr;
        }

        Claims claims = null;
        try {
            claims = JwtUtil.verifyToken(token);
        } catch (ExpiredJwtException expiredJwtException) {
            logger.error("token 已过期", expiredJwtException);
            dealErrorReturn(request, response, JsonUtil.objectToJson(new Result(false, "token已过期")));
            return false;
        } catch (Exception e) {
            logger.error("token 不合法", e);
            dealErrorReturn(request, response, JsonUtil.objectToJson(new Result(false, "token不合法")));
            return false;
        }
        if (claims == null) {
            dealErrorReturn(request, response, JsonUtil.objectToJson(new Result(false, "token不合法")));
            return false;
        }

        String tokenKey = claims.getId();
        String memToken = TokenInfoService.tokenMap.get(tokenKey);
        if (!token.equals(memToken)) {
            logger.error("token 已失效");
            dealErrorReturn(request, response, JsonUtil.objectToJson(new Result(false, "token 已失效")));
            return false;
        }
        String url = request.getRequestURI();
        logger.info("==================apiUrl:" + url);
        String userId = tokenKey;
        if (tokenKey.contains(";")) {
            userId = tokenKey.split(";")[0];
        }
        boolean verifyFlag = apiVerifyService.verifyApiUrl(userId, url);
        if (!verifyFlag) {
            dealErrorReturn(request, response, JsonUtil.objectToJson(new Result(false, "没有权限！")));
            return false;
        }
        User user = userService.get(userId);
        if (user == null) {
            dealErrorReturn(request, response, JsonUtil.objectToJson(new Result(false, "该用户不存在！")));
            return false;
        }
        SessionUtil.setCurrentUserName(user.getUsername());
        return true;
    }


    // 检测到没有token，直接返回不验证
    private void dealErrorReturn(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object obj) {
        String json = (String) obj;
        PrintWriter writer = null;
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("text/html; charset=utf-8");
        try {
            writer = httpServletResponse.getWriter();
            writer.print(json);

        } catch (IOException ex) {
            logger.error("response error", ex);
        } finally {
            if (writer != null)
                writer.close();
        }
    }
}
